<template>
    <layoutHeader></layoutHeader>
    <div>
        <div class="all">
            <video class="video" ref="localCameraVideo"></video>
            <video class="video" ref="remoteCameraVideo"></video>
            <div v-if="isRoomBusy">工作人员繁忙或不在线，请稍后再试!!!</div>
        </div>
        <div class="buttons">
            <button v-if ="!calling && !communicating && !isRoomBusy " class="button" @click="upVideo">拨打</button>
            <button v-if="calling && called" class="button" @click="yesVideo">接听</button>
            <button v-if="communicating || calling" class="button" @click="downVideo">挂断</button>
        </div>
    </div>
    <layoutFooter></layoutFooter>

</template>

<script setup>

import { onMounted, ref } from "vue";
import { getInfoService } from "@/api/user";
import { usePhoneStore } from "@/stores/phone";

const roomId = ref()    //房间号
const localCameraVideo = ref();   //自己的媒体
const remoteCameraVideo = ref();  //别人的媒体
const called = ref(false) //是否是接收方
const caller = ref(false) //是否是发起方
const calling = ref(false) //呼叫中
const communicating = ref(false) //视频通话中
const peer = ref()
const localStream = ref()
const isRoomBusy = ref(false)
const userId = ref()
let socket;

onMounted(() => {
    creatSocket(); 
});

//建立websocket
async function creatSocket(){
    await getUserId();
    socket = new WebSocket(`wss://192.168.58.147:8443/websocket/${userId.value}`)
    socket.onopen = function(){
        console.log('websocket打开')
        roomId.value = '0';
        socket.send(JSON.stringify({
            type: 'joinRoom',
            roomId: roomId.value
        }));
    }
    socket.addEventListener('message', async(message) => {
        const dataJson = JSON.parse(message.data);
        // 处理接收到的消息

        //用户收到自己被分配的房间号，如果没被分配，则是0,提示工作人员繁忙请稍后再试
        if(dataJson.type == 'getRoomId'){
            console.log(dataJson)
            if(dataJson.roomId == '0')
                isRoomBusy.value = true;
            else
                roomId.value = BigInt(dataJson.roomId);
        }
        //被呼叫方 接收到 呼叫方 请求通话的消息
        if(dataJson.type == 'callRemote' && !caller.value){ //不是呼叫方
            console.log('被呼叫方 接收到 呼叫方 请求通话的消息');

            called.value = true;
            calling.value = true;
        }
        //呼叫方 接收到 被呼叫方 同意通话的消息，发送offer等验证信息
        if(dataJson.type == 'acceptCall' && caller.value){ //是呼叫方
            console.log('呼叫方 接收到 被呼叫方 同意通话的消息');
            peer.value = new RTCPeerConnection() 
            peer.value.addStream(localStream.value)

            //获取candidate信息
            peer.value.onicecandidate = (event) =>{
                if(event.candidate){
                    socket.send(JSON.stringify({
                        type: 'sendCandidate',
                        roomId: roomId.value,
                        candidate:event.candidate,
                        role:'caller'
                    }));
                }
            }

            //获取对方的音视频流
            peer.value.onaddstream = async (event) =>{
                communicating.value = true;
                calling.value = false;
                remoteCameraVideo.value.srcObject = event.stream
                await remoteCameraVideo.value.play();
            }
            //获取自己的offer
            const offer = await peer.value.createOffer({
                offerToReceiveAudio:1,
                offerToReceiveVideo:1
            })
            //在本地设置offer信息
            await peer.value.setLocalDescription(offer)
            //发送offer
            socket.send(JSON.stringify({
                type: 'sendOffer',
                roomId: roomId.value,
                offer:offer
            }));
        }
        //被呼叫方 接收到 呼叫方 发来的offer，回发answer等信息。
        if(dataJson.type == 'sendOffer' && !caller.value){ //不是呼叫方
            console.log('被呼叫方 接收到 呼叫方 发来的offer');
            peer.value = new RTCPeerConnection() 
            //添加本地音视频流
            await getUserMedia({ audio: true, video: true }).then(userMedia => {
                localCameraVideo.value.srcObject = userMedia;
                localCameraVideo.value.play();
                peer.value.addStream(userMedia)
            })

            //获取对方的音视频流
            peer.value.onaddstream = async(event) =>{
                communicating.value = true;
                calling.value = false;
                remoteCameraVideo.value.srcObject = event.stream
                await remoteCameraVideo.value.play();
            }

            //设置远端描述信息
            await peer.value.setRemoteDescription(dataJson.offer).then(()=>{
                //获取candidate信息
                peer.value.onicecandidate = (event) =>{
                    if(event.candidate){
                        socket.send(JSON.stringify({
                            type: 'sendCandidate',
                            roomId: roomId.value,
                            candidate:event.candidate,
                            role:'called'
                        }));
                    }
                }
            });

            //生成answer
            const answer = await peer.value.createAnswer();
            //在本地设置answer信息
            await peer.value.setLocalDescription(answer)
            //发送answer
            socket.send(JSON.stringify({
                type: 'sendAnswer',
                roomId: roomId.value,
                answer:answer
            }));
        }
        //呼叫方 接收到 被呼叫方 发来的answer等信息，设置远端描述
        if(dataJson.type == 'sendAnswer' && caller.value){ //是呼叫方
            console.log('呼叫方 接收到 被呼叫方 发来的answer');
            await peer.value.setRemoteDescription(dataJson.answer);
        }
        //当双方收到对方发来的candidate信息时，调用addIceCandidate()
        if(dataJson.type == 'sendCandidate'){ 
            if( (caller.value && dataJson.role == 'called')||
            (called.value && dataJson.role == 'caller') ){
                console.log('接收到 对方 发来的candidate');
                try{
                    await peer.value.addIceCandidate(dataJson.candidate)
                }catch(error){
                    console.log("未能设置远端描述")
                }
            }  
        }
        //一方收到对方发来的挂断消息
        if(dataJson.type == 'hangUp'){ //被挂断的
            if(communicating.value){//如果是通话中被挂断的
            console.log('接收到 对方 发来的挂断消息');
            communicating.value = false;
            if(caller.value) caller.value = false;
            if(called.value) called.value = false;

            // 关闭 RTCPeerConnection
            if (peer.value) {
                peer.value.close(); 
                peer.value = null; 
            }

            // 停止所有媒体轨道
            if (localStream.value) {
                localStream.value.getTracks().forEach(track => track.stop());
                localStream.value = null;
            }
            
            if(localCameraVideo.value){
                const tracks = localCameraVideo.value.srcObject.getTracks();
                tracks.forEach(track => track.stop());
                localCameraVideo.value.srcObject = null;
            }

            if(remoteCameraVideo.value){
                const tracks = remoteCameraVideo.value.srcObject.getTracks();
                tracks.forEach(track => track.stop());
                remoteCameraVideo.value.srcObject = null;
            }}else if(called.value){
                console.log('接收到 对方 发来的挂断消息');
                called.value = false;
                calling.value = false;
            }else if(caller.value){
                console.log('接收到 对方 发来的挂断消息');
                caller.value = false;
                calling.value = false;

                if (localStream.value) {
                    localStream.value.getTracks().forEach(track => track.stop());
                    localStream.value = null;
                }

                if(localCameraVideo.value.srcObject){
                    const tracks = localCameraVideo.value.srcObject.getTracks();
                    tracks.forEach(track => track.stop());
                    localCameraVideo.value.srcObject = null;
                }
            }
        }
    });
    socket.onclose = function(){
        roomId.value = '0';
        console.log('websocket关闭')
    }
}    
//获取媒体信息
async function getUserMedia(constraints) {
    try {
        if (window.navigator.mediaDevices && window.navigator.mediaDevices.getUserMedia) {
            return await window.navigator.mediaDevices.getUserMedia(constraints);
        } else if (window.navigator.webkitGetUserMedia) {
            return await window.navigator.webkitGetUserMedia(constraints);
        } else if (window.navigator.mozGetUserMedia) {
            return await window.navigator.mozGetUserMedia(constraints);
        } else if (window.navigator.getUserMedia) {
            return await window.navigator.getUserMedia(constraints);
        } else {
            throw new Error('getUserMedia is not supported in this browser');
        }
    } catch (error) {
        console.error('Error accessing media devices.', error);
        throw error;
    }
}


//发起视频
const upVideo = async () =>{
    caller.value = true;
    calling.value = true;
    socket.send(JSON.stringify({
            type: 'callRemote',
            roomId: roomId.value
        }));
        
    await getUserMedia({ audio: true, video: true }).then(userMedia => {
        localStream.value = userMedia;
        localCameraVideo.value.srcObject = userMedia;
        localCameraVideo.value.play();
    })
}

//同意通话
const yesVideo = () =>{
    socket.send(JSON.stringify({
            type: 'acceptCall',
            roomId: roomId.value
        }));
}

//挂断通话
const downVideo = () => {
    caller.value = false;
    calling.value = false;
    communicating.value = false;
    if(caller.value) caller.value = false;
    if(called.value) called.value = false;
    socket.send(JSON.stringify({
        type: 'hangUp',
        roomId: roomId.value,
    }));

    // 关闭 RTCPeerConnection
    if (peer.value) {
        peer.value.close(); 
        peer.value = null; 
    }

    // 停止所有媒体轨道
    if (localStream.value) {
        localStream.value.getTracks().forEach(track => track.stop());
        localStream.value = null;
    }

    // 关闭 WebSocket 连接
    // if (socket) {
    //     socket.close();
    //     socket = null;
    // }

    if(localCameraVideo.value.srcObject){
        const tracks = localCameraVideo.value.srcObject.getTracks();
        tracks.forEach(track => track.stop());
        localCameraVideo.value.srcObject = null;
    }

    if(remoteCameraVideo.value.srcObject){
        const tracks = remoteCameraVideo.value.srcObject.getTracks();
        tracks.forEach(track => track.stop());
        remoteCameraVideo.value.srcObject = null;
    }
};

const getUserId = async() => {
    const phoneStore = usePhoneStore();
    const userInfo = await getInfoService(phoneStore.phone);
    userId.value = userInfo.data.data.userId;
}
</script>
    
<style>
.all{
    width: 360px;
    height: 480px;
    background-color: blue;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
.buttons {
    position: absolute;
    top: 600px; 
    left: 50%;
    transform: translateX(-50%); 
    display: flex; 
    gap: 10px; 
}

.button {
    padding: 10px 20px;
    background-color: rgb(30, 158, 167); 
    color: rgb(255, 255, 255); 
    border: none;
    border-radius: 5px; 
    cursor: pointer;
}
.video {
    width:360px ;
    height: 173px;
    background-color: #4CAF50;
    margin-top: 30px;
}
</style>